﻿using RockBus.Initialization.Interfaces;
using RockBus.Logging.Interfaces;
using System;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RockBus.Initialization
{
    public class TaskSchedulerInitialization : IInitialization
    {
        public TaskSchedulerInitialization(ILogger logger)
        {
            this.Logger = logger;
        }

        public ILogger Logger { get; set; }

        private static int _guard;

        public void Initialize()
        {
            if (Interlocked.CompareExchange(ref _guard, 1, 0) == 1)
            {
                return;
            }

            this.Logger.Log(MethodBase.GetCurrentMethod(), LogLevelEnum.Info, "Subscribing Logger to TaskScheduler.UnobservedTaskException.");

            try
            {
                TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs excArgs) =>
                {
                    var sb = new StringBuilder("UnobservedTaskException: ");
                    sb.AppendLine(excArgs.Exception.ToString());
                    var inner = excArgs.Exception.InnerException;
                    while (null != inner)
                    {
                        sb.AppendLine(inner.Message);
                        inner = inner.InnerException;
                    }
                    string text = sb.ToString();
                    this.Logger.Log(MethodBase.GetCurrentMethod(), LogLevelEnum.Error, text);
                    excArgs.SetObserved();
                };
            }
            catch (Exception exc)
            {
                if (null != this.Logger)
                {
                    this.Logger.Log(MethodBase.GetCurrentMethod(), exc);
                }
                else
                {
                    Trace.WriteLine(exc.ToString());
                }
                // throw;
            }
        }
    }
}